﻿// ------------------------------------------------------------------------------------------------
//  <copyright file="DimensionTable.cs" company="Iveely">
//    Copyright (c) Iveely Liu.  All rights reserved.
//  </copyright>
//  
//  <Create Time>
//    03/02/2013 21:59 
//  </Create Time>
//  
//  <contact owner>
//    liufanping@iveely.com 
//  </contact owner>
//  -----------------------------------------------------------------------------------------------

#region

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using IveelySE.NLP.Common.DataStructure.List;

#endregion

namespace IveelySE.NLP.Common.DataStructure.Table
{
    /// <summary>
    ///   二维表
    /// </summary>
    /// <typeparam name="TValue"> </typeparam>
    /// <typeparam name="TRow"> </typeparam>
    /// <typeparam name="TColumn"> </typeparam>
    [Serializable]
    public class DimensionTable<TColumn, TRow, TValue>
    {
        #region 属性或字段

        /// <summary>
        ///   列集合
        /// </summary>
        private readonly Hashtable _cloumns = new Hashtable();

        #endregion

        #region 内部类

        /// <summary>
        ///   列
        /// </summary>
        [Serializable]
        public class Cloumn<T2>
        {
            /// <summary>
            ///   列存储器
            /// </summary>
            private readonly ListTable<T2> _table = new ListTable<T2>();

            /// <summary>
            ///   索引器
            /// </summary>
            /// <param name="index"> </param>
            /// <returns> </returns>
            public object this[T2 index]
            {
                get { return _table[index]; }
                set { _table[index] = value; }
            }

            /// <summary>
            ///   获取所有的列集合
            ///   (将一列的所有提取出来)
            /// </summary>
            /// <returns> </returns>
            public SortedList<TValue> GetAllValue()
            {
                var result = new SortedList<TValue>();
                foreach(DictionaryEntry row in _table)
                {
                    result.Add((TValue) row.Value);
                }
                return result;
            }

            /// <summary>
            ///   获取所有的列集合
            ///   (将一列的所有提取出来以及文档编号)
            ///   小数部分是文档编号
            ///   整数部分是次数
            /// </summary>
            /// <returns> </returns>
            public SortedList<TValue> GetAllKeyValue()
            {
                var result = new SortedList<TValue>();
                foreach(DictionaryEntry row in _table)
                {
                    TValue r = ConvertType(row.Value + "." + row.Key);
                    result.Add(r);
                }
                return result;
            }

            #region 私有方法

            /// <summary>
            ///   泛型数据类型转换
            /// </summary>
            /// <param name="value"> 传入需要转换的值 </param>
            /// <returns> </returns>
            private TValue ConvertType(object value)
            {
                return (TValue) ConvertToT(value);
            }


            /// <summary>
            ///   转换数据类型
            /// </summary>
            /// <param name="myvalue"> 传入需要转换的值 </param>
            /// <returns> </returns>
            private object ConvertToT(object myvalue)
            {
                TypeCode typeCode = Type.GetTypeCode(typeof(TValue));
                string value = myvalue.ToString();
                switch(typeCode)
                {
                    case TypeCode.Boolean:
                        bool flag = false;
                        if(bool.TryParse(value, out flag))
                            return flag;
                        break;
                    case TypeCode.Char:
                        char c;
                        if(Char.TryParse(value, out c))
                            return c;
                        break;
                    case TypeCode.SByte:
                        sbyte s = 0;
                        if(SByte.TryParse(value, out s))
                            return s;
                        break;
                    case TypeCode.Byte:
                        byte b;
                        if(Byte.TryParse(value, out b))
                            return b;
                        break;
                    case TypeCode.Int16:
                        Int16 i16 = 0;
                        if(Int16.TryParse(value, out i16))
                            return i16;
                        break;
                    case TypeCode.UInt16:
                        UInt16 ui16 = 0;
                        if(UInt16.TryParse(value, out ui16))
                            return ui16;
                        break;
                    case TypeCode.Int32:
                        int i = 0;
                        if(Int32.TryParse(value, out i))
                            return i;
                        break;
                    case TypeCode.UInt32:
                        UInt32 ui32 = 0;
                        if(UInt32.TryParse(value, out ui32))
                            return ui32;
                        break;
                    case TypeCode.Int64:
                        Int64 i64 = 0;
                        if(Int64.TryParse(value, out i64))
                            return i64;
                        break;
                    case TypeCode.UInt64:
                        UInt64 ui64 = 0;
                        if(UInt64.TryParse(value, out ui64))
                            return ui64;
                        break;
                    case TypeCode.Single:
                        Single single = 0;
                        if(Single.TryParse(value, out single))
                            return single;
                        break;
                    case TypeCode.Double:
                        double d = 0;
                        if(Double.TryParse(value, out d))
                            return d;
                        break;
                    case TypeCode.Decimal:
                        decimal de = 0;
                        if(Decimal.TryParse(value, out de))
                            return de;
                        break;
                    case TypeCode.DateTime:
                        DateTime dt;
                        if(DateTime.TryParse(value, out dt))
                            return dt;
                        break;
                    case TypeCode.String:
                        if(value.Length == 0)
                            return "";
                        return value;
                }
                throw new ArgumentNullException("myvalue", "不能为Empty,Object,DBNull");
            }

            #endregion
        }

        #endregion

        #region 公有方法

        /// <summary>
        ///   列访问索引器
        /// </summary>
        /// <param name="index"> </param>
        /// <returns> </returns>
        public Cloumn<TRow> this[TColumn index]
        {
            get
            {
                if(!_cloumns.ContainsKey(index))
                {
                    _cloumns.Add(index, new Cloumn<TRow>());
                }
                return (Cloumn<TRow>) _cloumns[index];
            }
            set { _cloumns[index] = value; }
        }

        /// <summary>
        ///   根据行名字，获取整行数据
        ///   类似于我们选中某行，我们将选中某行的数据
        ///   以列表的形式取出
        /// </summary>
        /// <param name="name"> The name. </param>
        /// <returns> </returns>
        public SortedList<TValue> GetValueByName(TRow name)
        {
            if(!_cloumns.ContainsKey(name))
            {
                return null;
            }
            return ((Cloumn<TRow>) _cloumns[name]).GetAllValue();
        }

        /// <summary>
        ///   根据行名字，获取整行数据
        ///   类似于我们选中某行，我们将选中某行的数据
        ///   以列表的形式取出
        /// </summary>
        /// <returns> </returns>
        public SortedList<TValue> GetKeyValueByName(TRow name)
        {
            if(!_cloumns.ContainsKey(name))
            {
                return null;
            }
            return ((Cloumn<TRow>) _cloumns[name]).GetAllKeyValue();
        }

        /// <summary>
        ///   获取第一列集合
        /// </summary>
        /// <returns> </returns>
        public List<TRow> GetFirstCloumns()
        {
            var result = new List<TRow>();
            //读取每一行
            foreach(DictionaryEntry cloumn in _cloumns)
            {
                result.Add((TRow) cloumn.Key);
            }
            return result;
        }

        /// <summary>
        ///   根据列的名字清楚列数据(不建议常用，效率较低，会去读取每一行然后去删除该列)
        /// </summary>
        /// <param name="name"> </param>
        public void CleanByColumnName(TRow name)
        {
            //读取每一行
            foreach(DictionaryEntry cloumn in _cloumns)
            {
                //删除改行中所有相关数据
                ((Hashtable) cloumn.Value).Remove(name);
            }
        }

        #endregion

        #region 测试

        [Conditional("DEBUG")]
        public static void Test()
        {
            var table = new DimensionTable<string, int, double>();
            table["a"][1] = 0.01;
            table["b"][2] = 0.02;
            Console.WriteLine(table["a"][1]);
            Console.WriteLine(table["b"][2]);
        }

        #endregion
    }
}